package com.xuxueli.applyModules.utils.testquarts;

import com.alibaba.excel.util.DateUtils;
import com.cronutils.descriptor.CronDescriptor;
import com.cronutils.model.Cron;
import com.cronutils.model.definition.CronDefinition;
import com.cronutils.model.definition.CronDefinitionBuilder;
import com.cronutils.parser.CronParser;
import org.quartz.CronExpression;
import org.quartz.TriggerUtils;
import org.quartz.impl.triggers.CronTriggerImpl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import static com.cronutils.model.CronType.QUARTZ;

/**
 *cron表达式工具类
 *
 */
public class CronUtils {

    public static void main(String[] args) {
        ServiceScheduler serviceScheduler = new ServiceScheduler();
        serviceScheduler.startSchedule("tesy","etwe",12L,null);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        String scheduleTime = DateUtils.format(new Date());
        LocalDateTime localSetTime = LocalDateTime.parse(scheduleTime, formatter);
        long localSetTimeMill = localSetTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        if (localSetTimeMill < System.currentTimeMillis()) {
            scheduleTime = Instant.ofEpochMilli(System.currentTimeMillis()).atZone(ZoneId.systemDefault()).format(formatter);
        }
        System.out.println(scheduleTime);
        String expressiion = "0 0/2 * * * ?";
        boolean valid = CronUtils.isValid(expressiion);
        System.out.println("Cron表达式的有效性："+valid);
        String cronMessage = CronUtils.getCronMessage(expressiion);
        System.out.println("返回cron表达式："+cronMessage);
        String invalidMessage = CronUtils.getInvalidMessage(expressiion);
        System.out.println("有效返回null，无效返回信息："+invalidMessage);
        Date nextExecution = CronUtils.getNextExecution(expressiion);
        System.out.println("返回下一个执行时间："+nextExecution);
        //格式校验
        boolean b = checkValid(expressiion);
        System.out.println(b);
        if (b) {
            //解释cron表达式
            String s = describeCron(expressiion);
            System.out.println(s);
            //获取下次运行时间
            List<Date> nextExecTime = null;
            try {
                nextExecTime = getNextExecTime(expressiion, 5);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            nextExecTime.stream().forEach(d -> {
                System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(d));
            });
        }
    }

    /**
     * 解释cron表达式
     */
    public static String describeCron(String expressiion) {
        CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(QUARTZ);
        CronParser parser = new CronParser(cronDefinition);
        Cron cron = parser.parse(expressiion);
        //设置语言
        CronDescriptor descriptor = CronDescriptor.instance(Locale.CHINESE);
        return descriptor.describe(cron);
    }

    /**
     * 检查cron表达式的合法性
     *
     * @param cron cron exp
     * @return true if valid
     */
    public static boolean checkValid(String cron) {
        try {
            CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(QUARTZ);
            CronParser parser = new CronParser(cronDefinition);
            parser.parse(cron);
        } catch (IllegalArgumentException e) {
            System.out.println(String.format("cron=%s not valid", cron));
            return false;
        }
        return true;
    }

    /**
     * @param cronExpression cron表达式
     * @param numTimes       下一(几)次运行的时间
     * @return
     */
    public static List<Date> getNextExecTime(String cronExpression, Integer numTimes) throws ParseException {
        List<String> list = new ArrayList<>();
        CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();
        cronTriggerImpl.setCronExpression(cronExpression);
        // 这个是重点，一行代码搞定
        return TriggerUtils.computeFireTimes(cronTriggerImpl, null, numTimes);
    }

    /**
     * 返回一个布尔值代表一个给定的Cron表达式的有效性
     *
     * @param cronExpression Cron表达式
     * @return boolean 表达式是否有效
     */
    public static boolean isValid(String cronExpression) {
        return CronExpression.isValidExpression(cronExpression);
    }

    /**
     * 返回cron表达式
     * @param cronExpression
     * @return
     */
    public static String getCronMessage(String cronExpression) {
        try {
            CronExpression cronExpression1 = new CronExpression(cronExpression);
            return cronExpression1.toString();
        }
        catch (ParseException pe) {
            return pe.getMessage();
        }
    }

    /**
     * 返回一个字符串值,表示该消息无效Cron表达式给出有效性
     *
     * @param cronExpression Cron表达式
     * @return String 无效时返回表达式错误描述,如果有效返回null
     */
    public static String getInvalidMessage(String cronExpression) {
        try {
            new CronExpression(cronExpression);
            return null;
        }
        catch (ParseException pe) {
            return pe.getMessage();
        }
    }

    /**
     * 返回下一个执行时间根据给定的Cron表达式
     *
     * @param cronExpression Cron表达式
     * @return Date 下次Cron表达式执行时间
     */
    public static Date getNextExecution(String cronExpression) {
        try {
            CronExpression cron = new CronExpression(cronExpression);
            return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
        }
        catch (ParseException e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }
}